package edu.bw.advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * ServiceAdvice代表一个通知类,通知分很多类型
 *   前置通知:再目标方法执行前执行(在目标方法执行之前插入的通知)
 *   后置通知:目标方法正常执行并且返回后,执行后置通知,如果目标方法排除异常m无法执行后置通知
 *   最终通知(类似finally代码块):无论是目标方法在执行过程是否出现异常,最终通知都会执行
 *   异常通知:目标方法抛出异常后执行的通知,如果目标方法没有抛出异常,不执行异常操作
 *
 *   环绕通知(功能最强):环绕通知可以实现以上四种通知,还能控制目标方法是否执行,以及获取目标方法的参数,返回值等
 *
 */
@Component
@Aspect  //相当于<aop:aspect ref="serviceAdvice02">
public class ServiceAdvice02 {

    /**
     * @Pointcut  统一绑定切点表达式,通知中可以直接使用
     */
    @Pointcut("execution(* edu.bw.service..*.*(..))")
    public void pointcut(){

    }

/*    @Before("pointcut()")
    public void beforeAdvice(JoinPoint joinPoint){
        System.out.println(Arrays.toString(joinPoint.getArgs()) + "  " + joinPoint.getSignature());
        System.out.println("前置通知");
    }

    @AfterReturning(pointcut = "pointcut()",returning = "retVal")
    public void afterReturningAdvice(JoinPoint joinPoint,Object retVal){
        System.out.println(Arrays.toString(joinPoint.getArgs())+" "+joinPoint.getSignature());
        System.out.println("获取到的返回值是:"+retVal);
        System.out.println("后置通知");
    }


    @After("pointcut()")
    public void finallyAdvice(){
        System.out.println("最终通知");
    }

    @AfterThrowing(pointcut = "pointcut()",throwing = "throwable")
    public void afterThrowingAdvice(Throwable throwable){
        System.out.println("获取异常信息:"+throwable.getMessage());
        System.out.println("异常通知");
    }*/

    @Around("pointcut()")
    public void aroundAdvice(ProceedingJoinPoint pjp){
//        System.out.println("环绕通知");
        System.out.println(Arrays.toString(pjp.getArgs())+" "+pjp.getSignature());
        try {
            System.out.println("前置通知");
            Object retVal = pjp.proceed();//相当于执行目标方法  proceed()就相当于执行目标方法,其返回值就是目标方法的返回值
            System.out.println("获取到的返回值:"+retVal);
            System.out.println("后置通知");
        } catch (Throwable e) {
            System.out.println("异常重置");
            System.out.println("获取异常信息:"+e.getMessage());
            throw new RuntimeException(e);
        }finally {
            System.out.println("最终通知");
        }

    }


}
